package com.etime.shycourse.controller.pay2;

import com.etime.shy.common.BaseMessage;
import com.etime.shycourse.controller.pay.WXProgramPay;
import com.etime.shycourse.orde.pojo.Orders;
import com.etime.shycourse.services.interfaces.NotifyService;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.wxpay.sdk.WXPayUtil;
import com.google.common.collect.Maps;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

import static com.github.wxpay.sdk.WXPayUtil.*;

/**
 * 微信支付controller对象
 */
@Api(tags = "微信小程序支付2")
@RestController
@RequestMapping("/wx/pay2")
public class WXPayController {

    @Autowired
    private NotifyService notifyService;

    /**
     * 微信小程序支付统一下单接口
     * @param payentity
     * @return
     */
    @ApiOperation("微信小程序支付接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "orderNo",value = "订单号"),
            @ApiImplicitParam(name="orderPrice",value = "价格"),
            @ApiImplicitParam(name="productName",value = "商品名称"),
            @ApiImplicitParam(name="openId",value = "openid"),
            @ApiImplicitParam(name="remark",value = "备注")
    })
    @PostMapping("/program")
    public Map<String, String> wxprogrampay(@RequestBody WXProgramPay payentity, HttpServletRequest request){
        Map<String, String> map = Maps.newHashMap();
        map.put("appid", WXConfig.WECHAT_APPID);
        map.put("mch_id", WXConfig.WECHAT_MACH_ID);
        map.put("nonce_str", WXPayUtil.generateNonceStr());
        map.put("body", payentity.getRemark());
        map.put("out_trade_no", payentity.getOrderNo());
        map.put("total_fee", payentity.getOrderPrice());
        map.put("spbill_create_ip", getIpAddr(request));
        map.put("trade_type", WXConfig.tradeType);
        map.put("notify_url", WXConfig.NOTIFYURL);
        map.put("openid", payentity.getOpenId());
        // 微信统一下单URL
        String unifiedorderUrl = WXConfig.UNIFIED_ORDER_URL;
        // 生成签名 PAY_API_SECRET=微信支付相关API调用时使用的秘钥
        String sign = null;
        try {
            sign = generateSignature(map, WXConfig.WECHAT_key);
            // 参数配置 我直接写成"sign"
            map.put("sign", sign);
            String xml = mapToXml(map);
            //请求微信统一下单接口
            String xmlStr = HttpUtils.httpRequest(unifiedorderUrl, "POST", xml);
            Map map1 = HttpUtils.doXMLParse(xmlStr);
            //返回状态码
            String return_code = (String) map1.get("return_code");
            //返回状态码
            String result_code = (String) map1.get("result_code");
            //返回状态码
            String err_code = (String) map1.get("err_code");
            //返回状态码
            String err_code_des = (String) map1.get("err_code_des");
            if (return_code.equals("SUCCESS") || return_code.equals(result_code)) {
                // 业务结果
                //返回的预付单信息
                String prepay_id = (String) map1.get("prepay_id");
                Map<String, String> payMap = new HashMap<>();
                // 参数配置
                payMap.put("appId", WXConfig.WECHAT_APPID);
                //时间
                payMap.put("timeStamp", System.currentTimeMillis()+"");
                // 获取随机字符串
                payMap.put("nonceStr", generateNonceStr());
                payMap.put("signType", "MD5");
                payMap.put("package", "prepay_id=" + prepay_id);
                //第二次生成签名
                String paySign = generateSignature(payMap, WXConfig.WECHAT_key);
                payMap.put("paySign", paySign);
                //payMap.put("prepayId", prepay_id);
                payMap.remove("appId");
                //返回给前端，让前端去调支付 ，完成后你去调支付查询接口，看支付结果，处理业务。
                return payMap;
            } else {
                //打印失败日志
                System.out.println(err_code+":"+err_code_des);
            }
            return null;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 微信小程序支付回调接口，微信支付成功后自动调用
     * @param request
     * @return
     */
    @ApiOperation("微信小程序支付成功回调接口")
    @PostMapping("/notify")
    public String wxpaynotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        Map orderMap = new HashMap();
        BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream) request.getInputStream()));
        String line = null;
        StringBuilder sb = new StringBuilder();
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }
        String notityXml = sb.toString();
        System.out.println(notityXml);
        //保存原始反馈记录
        //notifyService.wxnotify(notityXml,resultm);

        String resXml = "";
        Map resPrint = new HashMap();
        Map<String, String> resultMap = WXPayUtil.xmlToMap(notityXml);
        //业务结果
        String returnCode = (String) resultMap.get("return_code");
        //订单号
        String orderNo = resultMap.get("out_trade_no");
        //获取微信签名
        String sign = resultMap.get("sign");
        //去除签名字段
        resultMap.remove("sign");
        //重新签名
        String signNew = WXPayUtil.generateSignature(resultMap, WXConfig.WECHAT_key);
        System.out.println(sign+"新的签名:"+signNew);
        if (signNew.equals(sign)) {
            if ("SUCCESS".equals(returnCode)) {
               // System.out.println(signNew + "ppppp");
                resPrint.put("return_code", "SUCCESS");
                resPrint.put("return_msg", "ok");
                resXml = WXPayUtil.mapToXml(resPrint);
                orderMap.put("orderStatus", 1);
                orderMap.put("orderNo", orderNo);
                // 自己的业务逻辑
                /*1、记录支付日志（支付返回的原始数据）
                  2、记录支付日志，拆分字段。
                  3、修改订单状态为“已完成”
                 */
                notifyService.wxnotify(notityXml,resultMap);

                return WxPayNotifyResponse.success("成功");
            } else {
                System.out.println("业务结果失败");
                //WxPayNotifyResponse.success("code:" + 9999 + "微信回调结果异常,异常原因:");
                return null;
            }

        } else {
            resPrint.put("return_code", "FAIL");
            resPrint.put("return_msg", "签名失败");
            resXml = WXPayUtil.mapToXml(resPrint);
        }
        //log.info(resXml);
        System.out.println(resXml);
        BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
        out.write(resXml.getBytes());
        out.flush();
        out.close();
        br.close();
        return null;
    }

    /**
     * 获取下单用户的ip地址
     * @param request
     * @return
     */
    private String getIpAddr(HttpServletRequest request){
        String ip = request.getHeader(("X-Forwarded-For"));
        if(StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)){
            int index = ip.indexOf(",");
            if(index!=-1){
                return ip.substring(0,index);
            }else{
                return ip;
            }
        }
        ip=request.getHeader("X-Real-IP");
        if(StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)){
            return ip;
        }
        return request.getRemoteAddr();
    }

    @ApiOperation("微信小程序支付后，根据订单号（orderno）查询订单状态")
    @GetMapping("/getorder")
    public Map<String,String> selectOrderState(String orderno){

        Map<String,String> resultMap = new HashMap<>();
        Orders orders = notifyService.selectOrderByNo(orderno);
        if(orders!=null){
            resultMap.put("code","1");
            resultMap.put("orderno",orderno);
            resultMap.put("orderid",orders.getOrderid().toString());
            resultMap.put("orderstate",orders.getOrderstate().toString());
            resultMap.put("orderpaycash",orders.getOrderpaycash().toString());
        }else{
            resultMap.put("code","0");
            resultMap.put("error_message","订单查询出错");
        }
        return resultMap;
    }

    /**
     * 支付使用优惠券或者虚拟币后，订单金额为0元的订单。
     * 业务逻辑：
     * 1）修改订单状态=2；支付金额=0
     * 2）修改订单使用的优惠券状态，修改为已使用；
     * 3）添加优惠券的使用日志
     * @param orderid 订单id
     * @return
     */
    @ApiOperation("使用优惠券后，订单金额为0元的订单处理")
    @ApiImplicitParam(name="orderid",value = "订单id")
    @PostMapping("/zero/{orderid}")
    public BaseMessage payzero(@PathVariable("orderid") Integer orderid){
        return notifyService.payzero(orderid);
    }
}
